import os
import re
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QFont, QIcon, QTextCharFormat, QBrush, QColor
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
                             QListWidget, QListWidgetItem, QLabel, QTextEdit, QSplitter,
                             QProgressBar, QMessageBox, QDialog)


class SearchWorker(QThread):
    """搜索工作线程"""
    progress_updated = pyqtSignal(int)
    result_found = pyqtSignal(str, str, int, str)  # file_path, line_content, line_number, match_text
    search_finished = pyqtSignal()
    
    def __init__(self, search_text, root_directory, file_patterns=None):
        super().__init__()
        self.search_text = search_text
        self.root_directory = root_directory
        self.file_patterns = file_patterns or ['.py', '.txt', '.js', '.html', '.css', '.json', '.xml', '.md', '.yaml',
                                               '.yml']
        self.cancel_flag = False
    
    def run(self):
        try:
            if not os.path.exists(self.root_directory):
                return
            
            # 获取所有文件
            all_files = []
            for root, dirs, files in os.walk(self.root_directory):
                for file in files:
                    if any(file.endswith(pattern) for pattern in self.file_patterns):
                        all_files.append(os.path.join(root, file))
            
            total_files = len(all_files)
            if total_files == 0:
                return
            
            # 搜索每个文件
            for i, file_path in enumerate(all_files):
                if self.cancel_flag:
                    break
                
                # 更新进度
                progress = int((i / total_files) * 100)
                self.progress_updated.emit(progress)
                
                try:
                    with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                        content = f.read()
                        lines = content.split('\n')
                        
                        for line_num, line_content in enumerate(lines, 1):
                            if self.search_text.lower() in line_content.lower():
                                # 高亮匹配文本
                                match_text = self.search_text
                                self.result_found.emit(file_path, line_content, line_num, match_text)
                except Exception as e:
                    continue
            
            self.search_finished.emit()
        except Exception as e:
            print(f"搜索错误: {e}")
    
    def cancel(self):
        self.cancel_flag = True


class SearchWindow(QDialog):
    """搜索窗口"""
    
    def __init__(self, parent=None, root_directory=""):
        super().__init__(parent)
        self.parent = parent
        self.root_directory = root_directory
        self.search_worker = None
        self.search_results = []
        
        self.setWindowTitle("全局搜索")
        self.setGeometry(100, 100, 1000, 700)
        self.setWindowFlags(Qt.Dialog | Qt.WindowCloseButtonHint)
        
        # 设置窗口图标
        icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "ide.ico")
        if os.path.exists(icon_path):
            self.setWindowIcon(QIcon(icon_path))
        
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        main_layout = QVBoxLayout()
        main_layout.setSpacing(10)
        main_layout.setContentsMargins(15, 15, 15, 15)
        
        # 标题栏
        title_layout = QHBoxLayout()
        title_label = QLabel("全局搜索")
        title_label.setFont(QFont("Microsoft YaHei", 14, QFont.Bold))
        title_label.setStyleSheet("color: #007ACC;")
        title_layout.addWidget(title_label)
        title_layout.addStretch()
        
        # 项目路径显示
        self.project_label = QLabel("")
        self.project_label.setFont(QFont("Microsoft YaHei", 9))
        self.project_label.setStyleSheet("color: #888888;")
        title_layout.addWidget(self.project_label)
        main_layout.addLayout(title_layout)
        
        # 搜索栏
        search_layout = QHBoxLayout()
        search_layout.setSpacing(10)
        
        # 搜索输入框
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("输入要搜索的内容...")
        self.search_input.setFont(QFont("Microsoft YaHei", 12))
        self.search_input.setMinimumHeight(35)
        self.search_input.returnPressed.connect(self.start_search)
        search_layout.addWidget(self.search_input)
        
        # 搜索按钮
        self.search_button = QPushButton("搜索")
        self.search_button.setFont(QFont("Microsoft YaHei", 10))
        self.search_button.setMinimumHeight(35)
        self.search_button.setMinimumWidth(80)
        self.search_button.clicked.connect(self.start_search)
        search_layout.addWidget(self.search_button)
        
        # 取消按钮
        self.cancel_button = QPushButton("取消")
        self.cancel_button.setFont(QFont("Microsoft YaHei", 10))
        self.cancel_button.setMinimumHeight(35)
        self.cancel_button.setMinimumWidth(80)
        self.cancel_button.clicked.connect(self.cancel_search)
        self.cancel_button.setEnabled(False)
        search_layout.addWidget(self.cancel_button)
        
        main_layout.addLayout(search_layout)
        
        # 搜索选项和统计信息
        options_layout = QHBoxLayout()
        options_layout.setSpacing(15)
        
        # 搜索选项
        options_label = QLabel("搜索选项：")
        options_label.setFont(QFont("Microsoft YaHei", 9))
        options_layout.addWidget(options_label)
        
        self.case_sensitive_check = QPushButton("区分大小写")
        self.case_sensitive_check.setCheckable(True)
        self.case_sensitive_check.setFont(QFont("Microsoft YaHei", 9))
        self.case_sensitive_check.setMinimumHeight(25)
        options_layout.addWidget(self.case_sensitive_check)
        
        self.whole_word_check = QPushButton("全字匹配")
        self.whole_word_check.setCheckable(True)
        self.whole_word_check.setFont(QFont("Microsoft YaHei", 9))
        self.whole_word_check.setMinimumHeight(25)
        options_layout.addWidget(self.whole_word_check)
        
        self.regex_check = QPushButton("正则表达式")
        self.regex_check.setCheckable(True)
        self.regex_check.setFont(QFont("Microsoft YaHei", 9))
        self.regex_check.setMinimumHeight(25)
        options_layout.addWidget(self.regex_check)
        
        options_layout.addStretch()
        
        # 文件类型筛选
        file_types_label = QLabel("文件类型：")
        file_types_label.setFont(QFont("Microsoft YaHei", 9))
        options_layout.addWidget(file_types_label)
        
        self.file_types_combo = QPushButton("所有文件")
        self.file_types_combo.setFont(QFont("Microsoft YaHei", 9))
        self.file_types_combo.setMinimumHeight(25)
        self.file_types_combo.setMinimumWidth(100)
        options_layout.addWidget(self.file_types_combo)
        
        # 结果统计
        self.result_count_label = QLabel("找到 0 个结果")
        self.result_count_label.setFont(QFont("Microsoft YaHei", 9, QFont.Bold))
        self.result_count_label.setStyleSheet("color: #007ACC;")
        options_layout.addWidget(self.result_count_label)
        
        main_layout.addLayout(options_layout)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        self.progress_bar.setMinimumHeight(8)
        main_layout.addWidget(self.progress_bar)
        
        # 主内容区域 - 使用分割器
        content_splitter = QSplitter(Qt.Horizontal)
        content_splitter.setChildrenCollapsible(False)
        
        # 左侧：搜索结果面板
        left_widget = QWidget()
        left_layout = QVBoxLayout(left_widget)
        left_layout.setContentsMargins(0, 0, 0, 0)
        
        # 结果列表标题
        results_title = QLabel("搜索结果")
        results_title.setFont(QFont("Microsoft YaHei", 11, QFont.Bold))
        results_title.setStyleSheet("color: #CCCCCC; padding: 5px; background-color: #252526; border-radius: 3px;")
        left_layout.addWidget(results_title)
        
        # 搜索结果列表
        self.results_list = QListWidget()
        self.results_list.setFont(QFont("Consolas", 9))
        self.results_list.setAlternatingRowColors(True)
        self.results_list.itemClicked.connect(self.on_result_selected)
        left_layout.addWidget(self.results_list)
        
        content_splitter.addWidget(left_widget)
        
        # 右侧：文件内容预览面板
        right_widget = QWidget()
        right_layout = QVBoxLayout(right_widget)
        right_layout.setContentsMargins(0, 0, 0, 0)
        right_layout.setSpacing(5)
        
        # 文件信息栏
        file_info_layout = QHBoxLayout()
        
        file_info_title = QLabel("文件预览")
        file_info_title.setFont(QFont("Microsoft YaHei", 11, QFont.Bold))
        file_info_title.setStyleSheet("color: #CCCCCC;")
        file_info_layout.addWidget(file_info_title)
        
        file_info_layout.addStretch()
        
        # 文件路径和行号
        self.file_path_label = QLabel("选择搜索结果查看文件内容")
        self.file_path_label.setFont(QFont("Microsoft YaHei", 9))
        self.file_path_label.setStyleSheet("color: #888888;")
        file_info_layout.addWidget(self.file_path_label)
        
        right_layout.addLayout(file_info_layout)
        
        # 内容预览区域
        self.content_preview = QTextEdit()
        self.content_preview.setFont(QFont("Consolas", 10))
        self.content_preview.setReadOnly(True)
        self.content_preview.setLineWrapMode(QTextEdit.NoWrap)
        right_layout.addWidget(self.content_preview)
        
        # 底部操作按钮
        bottom_buttons_layout = QHBoxLayout()
        
        self.open_file_button = QPushButton("打开文件")
        self.open_file_button.setFont(QFont("Microsoft YaHei", 9))
        self.open_file_button.setMinimumHeight(30)
        self.open_file_button.clicked.connect(self.open_selected_file)
        self.open_file_button.setEnabled(False)
        bottom_buttons_layout.addWidget(self.open_file_button)
        
        self.copy_line_button = QPushButton("复制行内容")
        self.copy_line_button.setFont(QFont("Microsoft YaHei", 9))
        self.copy_line_button.setMinimumHeight(30)
        self.copy_line_button.clicked.connect(self.copy_selected_line)
        self.copy_line_button.setEnabled(False)
        bottom_buttons_layout.addWidget(self.copy_line_button)
        
        bottom_buttons_layout.addStretch()
        
        self.clear_results_button = QPushButton("清空结果")
        self.clear_results_button.setFont(QFont("Microsoft YaHei", 9))
        self.clear_results_button.setMinimumHeight(30)
        self.clear_results_button.clicked.connect(self.clear_results)
        bottom_buttons_layout.addWidget(self.clear_results_button)
        
        right_layout.addLayout(bottom_buttons_layout)
        
        content_splitter.addWidget(right_widget)
        
        # 设置分割比例 (40% 结果列表, 60% 内容预览)
        content_splitter.setSizes([400, 600])
        
        main_layout.addWidget(content_splitter, 1)
        
        self.setLayout(main_layout)
        
        # 设置窗口大小和位置
        self.resize(1200, 800)
        
        # 设置样式
        self.apply_styles()
        
        # 更新项目路径显示
        if self.root_directory:
            self.project_label.setText(f"项目: {os.path.basename(self.root_directory)}")
    
    def apply_styles(self):
        """应用样式"""
        style = """
            QDialog {
                background-color: #252526;
                color: #CCCCCC;
            }
            QLabel {
                color: #CCCCCC;
            }
            QLineEdit {
                background-color: #3C3C3C;
                color: #FFFFFF;
                border: 1px solid #555555;
                border-radius: 4px;
                padding: 8px 12px;
                font-size: 12px;
            }
            QLineEdit:focus {
                border-color: #007ACC;
                background-color: #2D2D30;
            }
            QPushButton {
                background-color: #0E639C;
                color: #FFFFFF;
                border: none;
                border-radius: 4px;
                padding: 6px 12px;
                font-size: 11px;
            }
            QPushButton:hover {
                background-color: #1177BB;
            }
            QPushButton:pressed {
                background-color: #005A9E;
            }
            QPushButton:checked {
                background-color: #005A9E;
                border: 1px solid #007ACC;
            }
            QPushButton:disabled {
                background-color: #424242;
                color: #666666;
            }
            QListWidget {
                background-color: #1E1E1E;
                color: #D4D4D4;
                border: 1px solid #3E3E3E;
                border-radius: 4px;
                outline: none;
            }
            QListWidget::item {
                padding: 8px 12px;
                border-bottom: 1px solid #2D2D30;
                background-color: #252526;
            }
            QListWidget::item:alternate {
                background-color: #2A2A2A;
            }
            QListWidget::item:hover {
                background-color: #2A2D2E;
            }
            QListWidget::item:selected {
                background-color: #007ACC;
                color: #FFFFFF;
            }
            QTextEdit {
                background-color: #1E1E1E;
                color: #D4D4D4;
                border: 1px solid #3E3E3E;
                border-radius: 4px;
                font-family: 'Consolas', 'Monaco', monospace;
            }
            QTextEdit:focus {
                border-color: #007ACC;
            }
            QProgressBar {
                border: 1px solid #3E3E3E;
                border-radius: 4px;
                text-align: center;
                color: #FFFFFF;
                background-color: #2D2D30;
            }
            QProgressBar::chunk {
                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
                    stop:0 #007ACC, stop:1 #1177BB);
                border-radius: 2px;
            }
            QSplitter::handle {
                background-color: #3E3E3E;
            }
            QSplitter::handle:hover {
                background-color: #007ACC;
            }
        """
        self.setStyleSheet(style)
    
    def start_search(self):
        """开始搜索"""
        search_text = self.search_input.text().strip()
        if not search_text:
            QMessageBox.warning(self, "警告", "请输入搜索内容")
            return
        
        if not self.root_directory or not os.path.exists(self.root_directory):
            QMessageBox.warning(self, "警告", "请先打开项目文件夹")
            return
        
        # 清空之前的结果
        self.results_list.clear()
        self.search_results.clear()
        self.content_preview.clear()
        self.file_path_label.setText("搜索中...")
        
        # 显示进度条
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        
        # 禁用搜索按钮，启用取消按钮
        self.search_button.setEnabled(False)
        self.cancel_button.setEnabled(True)
        
        # 创建搜索工作线程
        self.search_worker = SearchWorker(search_text, self.root_directory)
        self.search_worker.progress_updated.connect(self.update_progress)
        self.search_worker.result_found.connect(self.add_search_result)
        self.search_worker.search_finished.connect(self.search_completed)
        self.search_worker.start()
    
    def cancel_search(self):
        """取消搜索"""
        if self.search_worker and self.search_worker.isRunning():
            self.search_worker.cancel()
            self.search_worker.wait()
        self.search_completed()
    
    def update_progress(self, value):
        """更新进度条"""
        self.progress_bar.setValue(value)
    
    def add_search_result(self, file_path, line_content, line_number, match_text):
        """添加搜索结果"""
        # 创建结果项
        file_name = os.path.basename(file_path)
        display_text = f"{file_name}:{line_number} - {line_content.strip()[:100]}"
        
        item = QListWidgetItem(display_text)
        item.setData(Qt.UserRole, {
            'file_path': file_path,
            'line_content': line_content,
            'line_number': line_number,
            'match_text': match_text
        })
        
        self.results_list.addItem(item)
        self.search_results.append({
            'file_path': file_path,
            'line_content': line_content,
            'line_number': line_number,
            'match_text': match_text
        })
        
        # 更新结果计数
        self.result_count_label.setText(f"找到 {len(self.search_results)} 个结果")
    
    def search_completed(self):
        """搜索完成"""
        self.progress_bar.setVisible(False)
        self.search_button.setEnabled(True)
        self.cancel_button.setEnabled(False)
        
        if len(self.search_results) == 0:
            self.file_path_label.setText("未找到匹配结果")
        else:
            self.file_path_label.setText(f"找到 {len(self.search_results)} 个结果")
    
    def on_result_selected(self, item):
        """选择搜索结果"""
        data = item.data(Qt.UserRole)
        if not data:
            return
        
        file_path = data['file_path']
        line_number = data['line_number']
        match_text = data['match_text']
        
        # 显示文件路径
        self.file_path_label.setText(f"文件: {file_path} (第{line_number}行)")
        
        # 读取并显示文件内容
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
                self.content_preview.setPlainText(content)
                
                # 高亮匹配行
                self.highlight_line(line_number, match_text)
        
        except Exception as e:
            self.content_preview.setPlainText(f"无法读取文件: {str(e)}")
    
    def highlight_line(self, line_number, match_text):
        """高亮显示匹配行"""
        # 移动到指定行
        cursor = self.content_preview.textCursor()
        cursor.movePosition(cursor.Start)
        
        # 移动到指定行
        for _ in range(line_number - 1):
            cursor.movePosition(cursor.Down)
        
        # 选择整行
        cursor.movePosition(cursor.StartOfLine)
        cursor.movePosition(cursor.EndOfLine, cursor.KeepAnchor)
        
        # 设置高亮格式
        highlight_format = QTextCharFormat()
        highlight_format.setBackground(QBrush(QColor(30, 60, 90)))  # 深蓝色背景
        
        # 应用高亮
        cursor.setCharFormat(highlight_format)
        
        # 滚动到高亮行
        self.content_preview.setTextCursor(cursor)
        self.content_preview.ensureCursorVisible()
    
    def on_result_selected(self, item):
        """选择搜索结果"""
        data = item.data(Qt.UserRole)
        if not data:
            return
        
        file_path = data['file_path']
        line_number = data['line_number']
        match_text = data['match_text']
        
        # 显示文件路径
        self.file_path_label.setText(f"文件: {os.path.basename(file_path)} (第{line_number}行)")
        
        # 启用操作按钮
        self.open_file_button.setEnabled(True)
        self.copy_line_button.setEnabled(True)
        
        # 读取并显示文件内容
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.read()
                self.content_preview.setPlainText(content)
                
                # 高亮匹配行
                self.highlight_line(line_number, match_text)
        
        except Exception as e:
            self.content_preview.setPlainText(f"无法读取文件: {str(e)}")
    
    def open_selected_file(self):
        """打开选中的文件"""
        current_item = self.results_list.currentItem()
        if not current_item:
            return
        
        data = current_item.data(Qt.UserRole)
        if not data:
            return
        
        file_path = data['file_path']
        line_number = data['line_number']
        
        # 通知主窗口打开文件
        if self.parent and hasattr(self.parent, 'openFileInTab'):
            self.parent.openFileInTab(file_path, line_number)
        
        # 关闭搜索窗口
        self.close()
    
    def copy_selected_line(self):
        """复制选中的行内容"""
        current_item = self.results_list.currentItem()
        if not current_item:
            return
        
        data = current_item.data(Qt.UserRole)
        if not data:
            return
        
        line_content = data['line_content'].strip()
        
        # 复制到剪贴板
        clipboard = QApplication.clipboard()
        clipboard.setText(line_content)
        
        QMessageBox.information(self, "复制成功", "行内容已复制到剪贴板")
    
    def clear_results(self):
        """清空搜索结果"""
        self.results_list.clear()
        self.search_results.clear()
        self.content_preview.clear()
        self.file_path_label.setText("选择搜索结果查看文件内容")
        self.result_count_label.setText("找到 0 个结果")
        self.open_file_button.setEnabled(False)
        self.copy_line_button.setEnabled(False)
    
    def set_root_directory(self, directory):
        """设置搜索根目录"""
        self.root_directory = directory
        if directory:
            self.setWindowTitle(f"全局搜索 - {os.path.basename(directory)}")
            self.project_label.setText(f"项目: {os.path.basename(directory)}")
        else:
            self.setWindowTitle("全局搜索")
            self.project_label.setText("")